package com.rs.game;

import java.util.concurrent.CopyOnWriteArrayList;

import com.rs.game.npc.NPC;
import com.rs.game.player.Player;

public final class RegionBuilder {

	/*
	 * build here the maps you wont edit again
	 */
	public static final void init() {
		//a small test, copying 100x100 area from lumby up to varrock to coords 4000-4100x 4000-4100y
		//copyAllPlanesMap(getRegion(3222), getRegion(3222), getRegion(4000), getRegion(4000), 100);
	}
	
	
	public static final int getRegion(int c) {
		return c >> 3;
	}
	
	
	public void cutRegion(int regionX, int regionY, int plane) {
		DynamicRegion toRegion = createDynamicRegion((((regionX / 8) << 8) + (regionY / 8)));
		int regionOffsetX = (regionX - ((regionX/8) * 8));
		int regionOffsetY = (regionY - ((regionY/8) * 8));
		toRegion.getRegionCoords()[plane][regionOffsetX][regionOffsetY][0] = 0;
		toRegion.getRegionCoords()[plane][regionOffsetX][regionOffsetY][1] = 0;
		toRegion.getRegionCoords()[plane][regionOffsetX][regionOffsetY][2] = 0;
		toRegion.getRegionCoords()[plane][regionOffsetX][regionOffsetY][3] = 0;
	}
	/*
	 * copys a single 8x8 map tile and allows you to rotate it
	 */
	public static final void copyRegion(int fromRegionX, int fromRegionY, int fromPlane, int toRegionX, int toRegionY, int toPlane, int rotation) {
		DynamicRegion toRegion = createDynamicRegion((((toRegionX / 8) << 8) + (toRegionY / 8)));
		int regionOffsetX = (toRegionX - ((toRegionX/8) * 8));
		int regionOffsetY = (toRegionY - ((toRegionY/8) * 8));
		toRegion.getRegionCoords()[toPlane][regionOffsetX][regionOffsetY][0] = fromRegionX;
		toRegion.getRegionCoords()[toPlane][regionOffsetX][regionOffsetY][1] = fromRegionY;
		toRegion.getRegionCoords()[toPlane][regionOffsetX][regionOffsetY][2] = fromPlane;
		toRegion.getRegionCoords()[toPlane][regionOffsetX][regionOffsetY][3] = rotation;
	}
	
	/*
	 * copy a exactly square of map from a place to another
	 */
	public static final void copyAllPlanesMap(int fromRegionX, int fromRegionY, int toRegionX, int toRegionY, int ratio) {
		int[] planes = new int[4];
		for(int plane = 1; plane < 4; plane++)
			planes[plane] = plane;
		copyMap(fromRegionX, fromRegionY, toRegionX, toRegionY, ratio, ratio, planes, planes);
	}
	
	/*
	 * copy a square of map from a place to another
	 */
	public static final void copyMap(int fromRegionX, int fromRegionY, int toRegionX, int toRegionY, int ratio, int[] fromPlanes, int[] toPlanes) {
		copyMap(fromRegionX, fromRegionY, toRegionX, toRegionY, ratio, ratio, fromPlanes, toPlanes);
	}
	
	/*
	 * copy a rectangle of map from a place to another
	 */
	public static final void copyMap(int fromRegionX, int fromRegionY, int toRegionX, int toRegionY, int widthRegions, int heightRegions, int[] fromPlanes, int[] toPlanes) {
		if(fromPlanes.length != toPlanes.length)
			throw new RuntimeException("PLANES LENGTH ISNT SAME OF THE NEW PLANES ORDER!");
		for(int xOffset = 0; xOffset < widthRegions; xOffset++) {
			for(int yOffset = 0; yOffset < heightRegions; yOffset++) {
				int fromThisRegionX = fromRegionX+xOffset;
				int fromThisRegionY = fromRegionY+yOffset;
				int toThisRegionX = toRegionX+xOffset;
				int toThisRegionY = toRegionY+yOffset;
				DynamicRegion toRegion = createDynamicRegion((((toThisRegionX / 8) << 8) + (toThisRegionY / 8)));
				int regionOffsetX = (toThisRegionX - ((toThisRegionX/8) * 8));
				int regionOffsetY = (toThisRegionY - ((toThisRegionY/8) * 8));
				for(int pIndex = 0; pIndex < fromPlanes.length; pIndex++) {
					int toPlane = toPlanes[pIndex];
					toRegion.getRegionCoords()[toPlane][regionOffsetX][regionOffsetY][0] = fromThisRegionX;
					toRegion.getRegionCoords()[toPlane][regionOffsetX][regionOffsetY][1] = fromThisRegionY;
					toRegion.getRegionCoords()[toPlane][regionOffsetX][regionOffsetY][2] = fromPlanes[pIndex];
				}
			}
		}
	}
	
	/*
	 * not recommended to use unless you want to make a more complex map
	 */
	public static final DynamicRegion createDynamicRegion(int regionId) {
		Region region = World.getRegions().get(regionId);
		if(region != null) {
			if(region instanceof DynamicRegion) //if its already dynamic lets keep building it
				return (DynamicRegion) region;
		}
		DynamicRegion newRegion = new DynamicRegion(regionId);
		World.getRegions().put(regionId, newRegion);
		return newRegion;
	}	
	
	/*
	 * Safely destroys a dynamic region
	 */
	public static final void destroyDynamicRegion(int regionId) {
		Region region = World.getRegions().get(regionId);
		if(region != null) {
			CopyOnWriteArrayList<Integer> playerIndexes = region.getPlayerIndexes();
			CopyOnWriteArrayList<Integer> npcIndexes = region.getNPCsIndexes();
			if(npcIndexes != null) {
				for(int npcIndex : npcIndexes) {
					NPC npc = World.getNPCs().get(npcIndex);
					if(npc == null)
						continue;
					if(npc.getRespawnTile().getRegionId() == regionId)
						World.removeNPC(npc);
					else
						npc.setNextWorldTile(new WorldTile(npc.getRespawnTile()));
				}
			}
			World.getRegions().remove(regionId);
			if(playerIndexes != null) {
				for(int playerIndex : playerIndexes) {
					Player player = World.getPlayers().get(playerIndex);
					if(player == null || !player.hasStarted() || player.hasFinished())
						continue;
					player.setForceNextMapLoadRefresh(true);
					player.loadMapRegions();
				}
			}
		}
	}
	
	private RegionBuilder() {
		
	}
}
